package org.dylan.evernote;

import java.io.File;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.dylan.keepnote.KNote;
import org.dylan.keepnote.KNoteExtractor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.evernote.edam.error.EDAMSystemException;
import com.evernote.edam.type.Data;
import com.evernote.edam.type.Note;
import com.evernote.edam.type.Notebook;
import com.evernote.edam.type.Resource;
import com.evernote.edam.type.ResourceAttributes;

/**
 * 
 * 
 * @Copyright: Copyright (c) 2013 FFCS All Rights Reserved
 * @Company: 北京福富软件有限公司
 * @author 陈作朋 Oct 27, 2013
 * @version 1.00.00
 * @history:
 * 
 */
public class KeepnoteToNote {
	
	private final static Logger logger = LoggerFactory.getLogger(KeepnoteToNote.class);

	private final static Logger successLogger = LoggerFactory.getLogger("ktoe.success");

	private final static Logger failedLogger = LoggerFactory.getLogger("ktoe.failed");
	
	private final static Logger notebookLogger = LoggerFactory.getLogger("ktoe.notebook");

	private final static String STACK = "KeepNote";

	private final static Set<String> successKNote = new HashSet<String>();
	
	private final static String NB_SEPARATOR="$$$";
	
	private static String nbGUID=null;

	static {
		File successFile = new File("logs//success.log");
		if (successFile.exists()) {
			try {
				successKNote.addAll(FileUtils.readLines(successFile));
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		} else {
			logger.error(successFile.getAbsolutePath() + " does not exist");
		}
		try {
			File nbFile=new File("logs//notebook.log");
			if (nbFile.exists()) {
				String nbStr = FileUtils.readFileToString(nbFile);
				String[] tmp = StringUtils.splitByWholeSeparator(nbStr, NB_SEPARATOR);
				if (tmp.length == 2) {
					nbGUID = tmp[1];
				}
			}else{
				logger.error(nbFile.getAbsolutePath() + " does not exist");
			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	public static String createNotebook(EDAMContext context, String name) throws Exception {
		if(StringUtils.isNotBlank(nbGUID)){
			logger.info("notebook is exist,GUID:"+nbGUID);
			return nbGUID;
		}
		Notebook notebook = new Notebook();
		notebook.setStack(STACK); // 组
		notebook.setName(name);
		Notebook createdNotebook = context.getNoteStore().createNotebook(notebook);
		logger.info("notebook guid:" + createdNotebook.getGuid());
		notebookLogger.info(name+NB_SEPARATOR+createdNotebook.getGuid());
		return createdNotebook.getGuid();
	}

	public static List<Resource> createResource(KNote knote) throws IOException, NoSuchAlgorithmException {

		List<Resource> result = new ArrayList<Resource>();

		String fileName = knote.getContent().getName();
		String mimeType = knote.getContentType();

		byte[] rData = FileUtils.readFileToByteArray(knote.getContent());

		Data data = new Data();
		data.setSize(rData.length);
		data.setBodyHash(MessageDigest.getInstance("MD5").digest(rData));
		data.setBody(rData);

		Resource resource = new Resource();
		resource.setData(data);
		resource.setMime(mimeType);
		ResourceAttributes attributes = new ResourceAttributes();

		if (rData.length > 3145728) { // 大于3M
			attributes.setAttachment(true);
		}

		attributes.setFileName(fileName);
		resource.setAttributes(attributes);
		result.add(resource);

		for (File img : knote.getImgs()) {

			String imgName = img.getName();

			String imgMimeType = FilenameUtils.getExtension(img.getAbsolutePath()).equalsIgnoreCase("gif") ? "image/gif" : "image/jpeg";

			byte[] bData = FileUtils.readFileToByteArray(img);

			Data imgData = new Data();
			imgData.setSize(bData.length);
			imgData.setBodyHash(MessageDigest.getInstance("MD5").digest(bData));
			imgData.setBody(bData);

			Resource imgResource = new Resource();
			imgResource.setData(imgData);
			imgResource.setMime(imgMimeType);
			ResourceAttributes imgAttributes = new ResourceAttributes();
			imgAttributes.setFileName(imgName);
			imgResource.setAttributes(imgAttributes);
			result.add(imgResource);
		}
		return result;
	}

	public static void createNote(EDAMContext context, String nbGUID, KNote knote) throws Exception {
		try {

			if (!knote.isNoteDir()) {
				
				if (null == knote.getContent()) {
					logger.info("======= content is empty - path:" + knote.getPath() + ",title:" + knote.getTitle());
					return;
				}

				String contentPath = knote.getContent().getAbsolutePath();

				if (successKNote.contains(contentPath)) {
					logger.info("+++++++ created note - " + contentPath);
					return;
				}
				
				Note note = new Note();
				note.setNotebookGuid(nbGUID);
				note.setTitle(knote.getTitle());

				List<Resource> resources = createResource(knote);

				String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
				xml += "<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">";
				xml += "<en-note>";

				for (Resource resource : resources) {
					note.addToResources(resource);
					String hashHexData = EDAMContext.bytesToHex(resource.getData().getBodyHash());
					xml += "<en-media type=\"" + resource.getMime() + "\" hash=\"" + hashHexData + "\"/>";
				}

				xml += "</en-note>";

				note.setContent(xml);

				note.setTagNames(Arrays.asList(new String[] { STACK, knote.getName() }));

				Note createdNote = context.getNoteStore().createNote(note);

				logger.info("note guid:" + createdNote.getGuid());

				successLogger.info(contentPath);

			}else{
				logger.info("-------- handle dir - path:" + knote.getPath() + ",title:" + knote.getTitle());
			}

			List<KNote> childs = knote.getChilds();
			for (KNote cknote : childs) {
				createNote(context, nbGUID, cknote);
			}

		} catch (EDAMSystemException e) {
			logger.error(e.getLocalizedMessage(),e);
			int wait = e.getRateLimitDuration() + 5;
			logger.info("wait:" + wait);
			Thread.sleep(wait * 1000);
			createNote(context, nbGUID, knote);
		} catch (Exception e) {
			failedLogger.info("{},caused by {}", knote.getContent().getAbsolutePath(), e.getLocalizedMessage());
			logger.error(e.getLocalizedMessage(),e);
		}
	}

	public static void createNote(String nbName, String path) throws Exception {
		try {
			EDAMContext context = new EDAMContext();
			KNote knote = KNoteExtractor.extract(path);
			logger.info("extract KeepNote completed");
			String nbGUID = createNotebook(context, nbName);
			createNote(context, nbGUID, knote);
		} catch (Exception e) {
			e.printStackTrace();
			if (e.getCause() instanceof EDAMSystemException) {
				EDAMSystemException edame = (EDAMSystemException) e.getCause();
				int wait = edame.getRateLimitDuration() + 5;
				logger.error("wait:" + wait);
				Thread.sleep(wait * 1000);
				createNote(nbName, path);
			}
		}
	}

	public static void main(String[] args) throws Exception {
		/*
		 * byte[] rData = FileUtils.readFileToByteArray(new File(
		 * "/home/dylan/Data/n/Linux/command/ssh/遠端連線伺服器ssh - xdmcp - vnc - rdp/linux_vbird_org_linux_server_0310telnets.pdf"
		 * )); System.out.println(rData.length);
		 */
/*		KNoteExtractor.seq=1;
		String path = "/home/dylan/Data/n/Linux/";
		createNote("K-Linux", path);*/
		// createNote("Java", path);
		
		KNoteExtractor.seq=607;
		String path = "/home/dylan/Data/n/Java/";
//		createNote("Java", path);

	}

}
